<script setup>
import { ref, reactive, computed, watch, watchEffect, toRefs, toRef, shallowRef, shallowReactive, markRaw, toRaw, isRef, isReactive, isProxy, customRef } from 'vue';
import CodeBlock from '@components/CodeBlock.vue';

// 1. 基础响应式API演示
const count = ref(0);
const message = ref('Hello Vue 3!');

const user = reactive({
  name: 'Vue开发者',
  age: 25,
  skills: ['JavaScript', 'Vue', 'CSS'],
  profile: {
    bio: '热爱前端开发',
    avatar: 'avatar.png'
  }
});

// 2. 计算属性演示
const doubleCount = computed(() => count.value * 2);
const userLevel = computed(() => {
  if (user.age >= 30) return '高级开发者';
  if (user.age >= 25) return '中级开发者';
  return '初级开发者';
});
const skillCount = computed(() => user.skills.length);

// 3. 监听演示
const watchLog = ref([]);

watch(count, (newVal, oldVal) => {
  addWatchLog(`计数从 ${oldVal} 变为 ${newVal}`);
});

// 深度监听
watch(
  () => user.profile,
  (newProfile, oldProfile) => {
    addWatchLog('用户简介已更新');
  },
  { deep: true }
);

// 监听多个源
watch(
  [count, message],
  ([newCount, newMessage], [oldCount, oldMessage]) => {
    addWatchLog(`计数或消息已更新: ${newCount}, ${newMessage}`);
  }
);

// 监听效果
const effectMessage = ref('');
watchEffect(() => {
  effectMessage.value = `当前计数: ${count.value}, 用户: ${user.name}`;
});

function addWatchLog(log) {
  watchLog.value.unshift(`${new Date().toLocaleTimeString()}: ${log}`);
  if (watchLog.value.length > 5) {
    watchLog.value.pop();
  }
}

// 4. 转换API演示
const { name, age } = toRefs(user);
const bioRef = toRef(user.profile, 'bio');

// 5. 高级响应式API
const shallowUser = shallowReactive({
  info: { name: '浅响应式用户' },
  settings: { theme: 'light' }
});

const shallowCounter = shallowRef({
  value: 0,
  nested: { count: 0 }
});

// 6. 非响应式数据
const nonReactiveLib = markRaw({
  version: '1.0.0',
  calculate: () => {
    console.log('这是一个非响应式库函数');
    return Math.random();
  }
});

const appState = reactive({
  name: 'My App',
  library: nonReactiveLib
});

// 7. 获取原始对象
const rawUser = toRaw(user);

// 8. 自定义响应式引用
function useDebouncedRef(value, delay = 300) {
  let timeout;
  return customRef((track, trigger) => ({
    get() {
      track();
      return value;
    },
    set(newValue) {
      clearTimeout(timeout);
      timeout = window.setTimeout(() => {
        value = newValue;
        trigger();
      }, delay);
    }
  }));
}

const searchQuery = useDebouncedRef('');
const debouncedResult = ref('');

watch(searchQuery, (newQuery) => {
  debouncedResult.value = `搜索: "${newQuery}" (防抖后)`;
});

// 9. 响应式检查
const reactiveChecks = {
  countIsRef: isRef(count),
  userIsReactive: isReactive(user),
  doubleCountIsRef: isRef(doubleCount),
  shallowUserIsReactive: isReactive(shallowUser),
  shallowCounterIsRef: isRef(shallowCounter),
  appStateIsProxy: isProxy(appState),
  libraryIsReactive: isReactive(appState.library),
  rawUserIsReactive: isReactive(rawUser)
};

// 操作方法
function incrementCount() {
  count.value++;
}

function updateMessage() {
  message.value = `更新于 ${new Date().toLocaleTimeString()}`;
}

function addSkill() {
  const newSkill = `技能${user.skills.length + 1}`;
  user.skills.push(newSkill);
}

function updateBio() {
  user.profile.bio = `新简介更新于 ${new Date().toLocaleTimeString()}`;
}

function updateShallow() {
  shallowUser.info.name = '更新后的名称'; // 不会触发响应
}

function replaceShallow() {
  shallowUser.info = { name: '完全替换的对象' }; // 会触发响应
}

function updateShallowCounter() {
  if (shallowCounter.value?.nested) {
    shallowCounter.value.nested.count++;
  }
}

function replaceShallowCounter() {
  shallowCounter.value = { 
    ...(shallowCounter.value || {}), 
    nested: { ...(shallowCounter.value?.nested || {}), count: 99 } 
  };
}

function callNonReactive() {
  const result = appState.library.calculate();
  message.value = `非响应式库结果: ${result ? result.toFixed(2) : '计算错误'}`;
}

function modifyRaw() {
  rawUser.name = '修改原始对象'; // 不会触发响应
  console.log('原始对象已修改，但不会触发视图更新');
}
</script>

<template>
  <div class="reactive-system-demo">
    <h2 class="demo-title">⚡ Vue 3 响应式系统全面演示</h2>
    
    <p class="demo-description">
      探索Vue 3基于Proxy的响应式系统，包括ref、reactive、computed等核心API的使用方法和最佳实践。
    </p>

    <div class="demo-grid">
      <!-- 1. 基础响应式API -->
      <div class="demo-card">
        <h3 class="card-title">基础响应式API</h3>
        <div class="demo-content">
          <div class="api-group">
            <h4>ref() - 基本类型响应式</h4>
            <div class="value-display">
              <p>count: {{ count }}</p>
              <button @click="incrementCount" class="btn">增加</button>
            </div>
            
            <h4>reactive() - 对象类型响应式</h4>
            <div class="user-info">
              <p>用户名: {{ user.name }}</p>
              <p>年龄: {{ user.age }}</p>
              <p>技能: {{ user.skills.join(', ') }}</p>
              <button @click="addSkill" class="btn">添加技能</button>
            </div>
          </div>
        </div>
      </div>

      <!-- 2. 计算属性 -->
      <div class="demo-card">
        <h3 class="card-title">计算属性 (computed)</h3>
        <div class="demo-content">
          <div class="computed-group">
            <p><strong>doubleCount:</strong> {{ doubleCount }}</p>
            <p><strong>userLevel:</strong> {{ userLevel }}</p>
            <p><strong>skillCount:</strong> {{ skillCount }}</p>
          </div>
          
          <CodeBlock language="javascript">
{`// 计算属性示例
const doubleCount = computed(() => count.value * 2);
const userLevel = computed(() => {
  if (user.age >= 30) return '高级开发者';
  if (user.age >= 25) return '中级开发者';
  return '初级开发者';
});`}
          </CodeBlock>
        </div>
      </div>

      <!-- 3. 监听效果 -->
      <div class="demo-card">
        <h3 class="card-title">监听 (watch & watchEffect)</h3>
        <div class="demo-content">
          <div class="watch-group">
            <input v-model="message" placeholder="输入消息" class="input" />
            <p><strong>effectMessage:</strong> {{ effectMessage }}</p>
            <div class="watch-logs">
              <h4>监听日志:</h4>
              <ul class="logs-list">
                <li v-for="(log, index) in watchLog" :key="index">{{ log }}</li>
              </ul>
            </div>
          </div>
        </div>
      </div>

      <!-- 4. 转换API -->
      <div class="demo-card">
        <h3 class="card-title">响应式转换API</h3>
        <div class="demo-content">
          <div class="conversion-group">
            <h4>toRefs() - 解构响应式对象</h4>
            <p>通过toRefs访问: {{ name.value }}, {{ age.value }}</p>
            
            <h4>toRef() - 创建特定属性的ref</h4>
            <p>用户简介: {{ bioRef.value }}</p>
            <button @click="updateBio" class="btn">更新简介</button>
          </div>
        </div>
      </div>

      <!-- 5. 浅层响应式 -->
      <div class="demo-card">
        <h3 class="card-title">浅层响应式API</h3>
        <div class="demo-content">
          <div class="shallow-group">
            <h4>shallowReactive</h4>
            <p>浅层用户: {{ shallowUser.info.name }}</p>
            <div class="btn-group">
              <button @click="updateShallow" class="btn btn-warning">修改嵌套属性</button>
              <button @click="replaceShallow" class="btn">替换对象</button>
            </div>
            
            <h4>shallowRef</h4>
            <p>嵌套计数: {{ shallowCounter.value?.nested?.count || 0 }}</p>
            <div class="btn-group">
              <button @click="updateShallowCounter" class="btn btn-warning">修改嵌套计数</button>
              <button @click="replaceShallowCounter" class="btn">替换整个对象</button>
            </div>
          </div>
        </div>
      </div>

      <!-- 6. 非响应式数据 -->
      <div class="demo-card">
        <h3 class="card-title">非响应式数据</h3>
        <div class="demo-content">
          <div class="non-reactive-group">
            <h4>markRaw - 标记非响应式</h4>
            <p>库版本: {{ appState.library.version }}</p>
            <button @click="callNonReactive" class="btn">调用库方法</button>
            
            <h4>toRaw - 获取原始对象</h4>
            <p>原始用户名: {{ rawUser.name }}</p>
            <button @click="modifyRaw" class="btn btn-warning">修改原始对象</button>
          </div>
        </div>
      </div>

      <!-- 7. 自定义响应式 -->
      <div class="demo-card">
        <h3 class="card-title">自定义响应式引用</h3>
        <div class="demo-content">
          <div class="custom-ref-group">
            <h4>customRef - 防抖搜索示例</h4>
            <input v-model="searchQuery" placeholder="搜索..." class="input" />
            <p class="debounced-result">{{ debouncedResult }}</p>
            
            <CodeBlock language="javascript">
{`// 自定义防抖引用
function useDebouncedRef(value, delay = 300) {
  let timeout;
  return customRef((track, trigger) => ({
    get() {
      track();
      return value;
    },
    set(newValue) {
      clearTimeout(timeout);
      timeout = setTimeout(() => {
        value = newValue;
        trigger();
      }, delay);
    }
  }));
}`}
            </CodeBlock>
          </div>
        </div>
      </div>

      <!-- 8. 响应式检查 -->
      <div class="demo-card">
        <h3 class="card-title">响应式状态检查</h3>
        <div class="demo-content">
          <div class="check-group">
            <table class="check-table">
              <tr v-for="(value, key) in reactiveChecks" :key="key">
                <td>{{ key }}</td>
                <td :class="{ 'true': value, 'false': !value }">{{ value ? '✓' : '✗' }}</td>
              </tr>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- 最佳实践部分 -->
    <div class="best-practices-section">
      <h3 class="section-title">响应式系统最佳实践</h3>
      <div class="practices-content">
        <div class="practice-grid">
          <div class="practice-item">
            <h4>✅ 推荐做法</h4>
            <ul>
              <li>对基本类型使用 <code>ref</code></li>
              <li>对对象使用 <code>reactive</code></li>
              <li>使用 <code>computed</code> 处理派生状态</li>
              <li>组件间传递响应式数据时使用 <code>toRefs</code></li>
              <li>第三方库实例使用 <code>markRaw</code></li>
              <li>大型对象考虑使用 <code>shallowReactive</code> 优化性能</li>
            </ul>
          </div>
          <div class="practice-item">
            <h4>❌ 避免做法</h4>
            <ul>
              <li>直接修改 <code>reactive</code> 对象的整个引用</li>
              <li>在模板中解构 <code>reactive</code> 对象</li>
              <li>期望 <code>shallowReactive</code> 响应嵌套属性变化</li>
              <li>过度使用 <code>watchEffect</code> 导致性能问题</li>
              <li>修改 <code>toRaw</code> 返回的对象后期望更新</li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.reactive-system-demo {
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}

.demo-title {
  text-align: center;
  margin-bottom: 10px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  font-size: 2.2rem;
}

.demo-description {
  text-align: center;
  margin-bottom: 30px;
  color: #666;
  font-size: 1.1rem;
}

.demo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
  gap: 24px;
  margin-bottom: 40px;
}

.demo-card {
  background: white; /* 浅色主题下为白色背景 */
  border-radius: 12px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  padding: 24px;
  transition: all 0.2s ease;
}

.demo-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

/* 深色主题下的样式 - 使用data-theme属性选择器 */
[data-theme="dark"] .demo-card {
  background: #000000; /* 深色主题下为黑色背景 */
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}

[data-theme="dark"] .demo-card:hover {
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
  border-color: rgba(255, 255, 255, 0.15);
}

.card-title {
  color: #667eea;
  margin-bottom: 20px;
  font-size: 1.3rem;
  border-bottom: 2px solid #f0f0f0;
  padding-bottom: 10px;
}

/* 深色主题下的标题样式 */
[data-theme="dark"] .card-title {
  color: #a5b4fc;
  border-bottom-color: rgba(255, 255, 255, 0.1);
}

.demo-content {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.value-display, .user-info, .computed-group, .watch-group, .conversion-group, .shallow-group, .non-reactive-group, .custom-ref-group, .check-group {
  background-color: #f9f9f9; /* 浅色主题下的浅色背景 */
  border-radius: 8px;
  padding: 16px;
  border-left: 3px solid #667eea;
  color: #333; /* 浅色主题下的文字颜色 */
}

/* 深色主题下内部组件样式 */
[data-theme="dark"] .value-display, 
[data-theme="dark"] .user-info, 
[data-theme="dark"] .computed-group, 
[data-theme="dark"] .watch-group, 
[data-theme="dark"] .conversion-group, 
[data-theme="dark"] .shallow-group, 
[data-theme="dark"] .non-reactive-group, 
[data-theme="dark"] .custom-ref-group, 
[data-theme="dark"] .check-group {
  background-color: rgba(255, 255, 255, 0.05); /* 深色主题下的深色背景 */
  border-left-color: #a5b4fc;
  color: #ffffff; /* 深色主题下的文字颜色 */
}

.input {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  margin-bottom: 10px;
  font-size: 14px;
}

.btn {
  padding: 8px 16px;
  background-color: #667eea;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.2s;
}

.btn:hover {
  background-color: #5a67d8;
}

.btn-warning {
  background-color: #eab308;
}

.btn-warning:hover {
  background-color: #ca8a04;
}

.btn-group {
  display: flex;
  gap: 10px;
  margin-top: 10px;
}

.watch-logs {
  margin-top: 15px;
}

.logs-list {
  list-style: none;
  padding: 0;
  margin: 0;
  max-height: 100px;
  overflow-y: auto;
  background-color: #f0f0f0;
  border-radius: 4px;
  padding: 8px;
}

.logs-list li {
  font-size: 12px;
  padding: 4px 0;
  color: #666;
  border-bottom: 1px solid #e0e0e0;
}

.logs-list li:last-child {
  border-bottom: none;
}

.debounced-result {
  margin-top: 10px;
  font-weight: bold;
  color: #667eea;
}

.check-table {
  width: 100%;
  border-collapse: collapse;
}

.check-table td {
  padding: 8px;
  border-bottom: 1px solid #e0e0e0;
}

.check-table td.true {
  color: #10b981;
  font-weight: bold;
}

.check-table td.false {
  color: #ef4444;
  font-weight: bold;
}

.best-practices-section {
  background: white;
  border-radius: 12px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  padding: 24px;
  transition: all 0.2s ease;
}

/* 深色主题下的最佳实践部分 */
[data-theme="dark"] .best-practices-section {
  background: #000000;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}

.section-title {
  color: #333;
  margin-bottom: 20px;
  font-size: 1.5rem;
}

/* 深色主题下的章节标题 */
[data-theme="dark"] .section-title {
  color: #ffffff;
}

.practice-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
}

.practice-item {
  background-color: #f9f9f9;
  border-radius: 8px;
  padding: 20px;
}

.practice-item h4 {
  margin-top: 0;
  margin-bottom: 15px;
  color: #333;
}

/* 深色主题下的实践项目 */
[data-theme="dark"] .practice-item {
  background-color: rgba(255, 255, 255, 0.05);
}

[data-theme="dark"] .practice-item h4 {
  color: #ffffff;
}

.practice-item ul {
  margin: 0;
  padding-left: 20px;
}

.practice-item li {
  margin-bottom: 8px;
  line-height: 1.5;
}

.practice-item code {
  background-color: #f1f1f1;
  padding: 2px 4px;
  border-radius: 3px;
  font-family: 'Courier New', monospace;
  font-size: 0.9em;
}

@media (max-width: 768px) {
  .demo-grid {
    grid-template-columns: 1fr;
  }
  
  .practice-grid {
    grid-template-columns: 1fr;
  }
  
  .btn-group {
    flex-direction: column;
  }
}
</style>